#include "RankSelection.h"
#include "../../Util/SolutionPtrComparator.h"

//since we've inherited from RouletteSelection, and since we
//populated the wheel in our prepare method, we can just forward
//this call to RouletteWheel's select method.
void RankSelection::select(Solution* &child1, Solution* &child2)
{
    RouletteSelection::select(child1, child2);
}

void RankSelection::prepare(vector<Solution*> newPool)
{
    clean();
    genePool = newPool;
    
    //sort the solutions into decending order
    sort(genePool.begin(), genePool.end(), SolutionPtrGTComparator());
    
    //since we are going to assign the solutions a fitness from size() to
    //1, we can calculate totalFitness directly - the sum of the integers 
    //from 1 to N is: N*(N+1)/2 (--http://www.mathpages.com/home/kmath107.htm)
    
    unsigned int genePoolSize = genePool.size();
    
    //note that N*(N+1) is always an even number, so integer division 
    //by 2 is safe here.    
    totalFitness = double((genePoolSize * (genePoolSize + 1)) / 2);
    
    double currentTotal = 0.0;
    
    for (unsigned int i = 0; i < genePoolSize; ++i)  
    {
        currentTotal += (double(genePoolSize - i) / totalFitness);
        wheel.push_back(currentTotal);
    }    
}

Selection* RankSelection::getSelection() {
    return new RankSelection();
}
